/****************************************************************************/
/***        Include files                                                 ***/
/****************************************************************************/
#include <stdarg.h>
#include <ctype.h>
#include "Printf.h"
#include <AppHardwareApi.h>
/****************************************************************************/
/***        Macro Definitions                                             ***/
/****************************************************************************/
/****************************************************************************/
/***        Type Definitions                                              ***/
/****************************************************************************/
/****************************************************************************/
/***        Local Function Prototypes                                     ***/
/****************************************************************************/
PRIVATE void vNum2String(uint32 u32Number,uint8 u8Base,uint16 uart);
/****************************************************************************/
/***        Exported Variables                                            ***/
/****************************************************************************/
/****************************************************************************/
/***        Local Variables                                               ***/
/****************************************************************************/
/* pointer to whatever putchar function the user gives us */
PRIVATE void (*vPutChar) (uint16 uart,char c)=NULL;
/****************************************************************************/
/***        Exported Functions                                            ***/
/****************************************************************************/
/*
* Before using these functions, you must call vInitPrintf
* and give it a pointer to a function that will write the individual
* characters to whatever device you decide to use for displaying output.
*
* example below :-
*
*   #include "Printf.h"
*
*   void main(void)
*   {
*
*       vInitPrintf((void*)vPutC);  // pass the pointer to the putc function
*
*       vPrintf("\nHello World!");  // show some text !
*       while(1);
*   }
*
*   void vPutC(char c)
*   {
*       do something with c here, maybe write it to a uart
*   }
*
*/
PUBLIC void vInitPrintf(void (*fp)(uint16 uart,char c))
{
    vPutChar=fp;
}
/*
 * printf()
 *  Print to display - really trivial implementation!
 */
PUBLIC void vPrintf(uint16 uart,const char *fmt,...)
{
    char *bp=(char *)fmt;
    va_list ap;
    char c;
    char *p;
    int32 i;

    va_start(ap,fmt);

    while((c= *bp++))
    {
        if(c!='%')
        {
            if(c=='\n')
            {
                vPutChar(uart,'\n');
                vPutChar(uart,'\r');
            }
            else
            {
                vPutChar(uart,c);
            }
            continue;
        }

        switch((c= *bp++))
        {

        /* %d - show a decimal value */
        case 'd':
            vNum2String(va_arg(ap,uint32),10,uart);
            break;

        /* %x - show a value in hex */
        case 'x':
            vPutChar(uart,'0');
            vPutChar(uart,'x');
            vNum2String(va_arg(ap,uint32),16,uart);
            break;

        /* %b - show a value in binary */
        case 'b':
            vPutChar(uart,'0');
            vPutChar(uart,'b');
            vNum2String(va_arg(ap,uint32),2,uart);
            break;

        /* %c - show a character */
        case 'c':
            vPutChar(uart,va_arg(ap,int));
            break;

        case 'i':
            i=va_arg(ap,int32);
            if(i<0)
            {
                vPutChar(uart,'-');
                vNum2String((~i)+1,10,uart);
            }
            else
            {
                vNum2String(i,10,uart);
            }
            break;

        /* %s - show a string */
        case 's':
            p=va_arg(ap,char *);
            do
            {
                vPutChar(uart,*p++);
            }while(*p);
            break;

        /* %% - show a % character */
        case '%':
            vPutChar(uart,'%');
            break;

        /* %something else not handled ! */
        default:
            vPutChar(uart,'?');
            break;
        }
    }

    return;
}
/****************************************************************************/
/***  Functions To Allow Printf To Work Via The UART                      ***/
/****************************************************************************/
/****************************************************************************
 *
 * NAME: vUART_printInit
 *
 * DESCRIPTION:
 * Initialises the UART print environment
 *
 * RETURNS:
 * void
 *
 ****************************************************************************/
PUBLIC void vUART_printInit(uint8 uart,uint8 rate,bool_t INT_ENABLE,uint8 fifo_level)
{
    vInitPrintf((void*)vPutC);
    vUART_Init(uart,rate,INT_ENABLE,fifo_level);
}
/****************************************************************************
 *
 * NAME: vUART_Init
 *
 * DESCRIPTION:
 * Initialises the UART
 *
 * RETURNS:
 * void
 *
 ****************************************************************************/
PUBLIC void vUART_Init(uint8 uart,uint8 rate,bool_t INT_ENABLE,uint8 fifo_level)
{
    /* Enable uart: rate-8-N-1 */
    vAHI_UartEnable(uart);

    vAHI_UartReset(uart,TRUE,TRUE);
    vAHI_UartReset(uart,FALSE,FALSE);

    vAHI_UartSetClockDivisor(uart,rate);
    vAHI_UartSetControl(uart,FALSE,FALSE,E_AHI_UART_WORD_LEN_8,TRUE,FALSE);
    //vAHI_UartSetInterrupt(uart,FALSE,INT_ENABLE,INT_ENABLE,INT_ENABLE,fifo_level);
    vAHI_UartSetInterrupt(uart,FALSE,FALSE,FALSE,INT_ENABLE,fifo_level);
}
/****************************************************************************
 *
 * NAME: vPutC
 *
 * DESCRIPTION:
 * UART Callback Function To Allow printf to work over the Serial Port
 *
 * RETURNS:
 * void
 *
 ****************************************************************************/
PUBLIC void vPutC(uint16 uart,unsigned char c)
{
    //wait for tx fifo empty (bit 5 set in LSR when empty)
    while((u8AHI_UartReadLineStatus(uart)&E_AHI_UART_LS_THRE)==0);
    // ..and send the character
    vAHI_UartWriteData(uart,c);
}
/****************************************************************************/
/***        Local Functions                                               ***/
/****************************************************************************/
/*
 * vNum2String()
 *  Convert a number to a string
 */
PRIVATE void vNum2String(uint32 u32Number,uint8 u8Base,uint16 uart)
{
    char buf[33];
    char *p=buf+33;
    uint32 c,n;

    *--p='\0';
    do{
        n=u32Number/u8Base;
        c=u32Number-(n *u8Base);
        if(c<10)
        {
            *--p='0'+c;
        }
        else
        {
            *--p ='a'+(c-10);
        }
        u32Number/=u8Base;
    }while(u32Number!=0);

    while(*p)
    {
        vPutChar(uart,*p);
        p++;
    }

    return;
}
/****************************************************************************/
/***        END OF FILE                                                   ***/
/****************************************************************************/


